﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Crystal
{    
    class Parser
    {
        /// <summary>
        /// The default name of file with initial conditions
        /// </summary>
        public const string defaultFile = "InitConds.txt";
        private const string commentSign = "#";

        private const string IC_FIELD_BOX      =  "BoxL";
        private const string IC_FIELD_NATOMS   =  "Natoms";
        private const string IC_FIELD_ATOMINF  =  "AtomInf";

        /// <summary>
        /// The form that will recieve status information and bring it to user
        /// </summary>        
        private static stWindow _stWindow;

        public static void init(stWindow stWin)
        {
            _stWindow = stWin;
        }

        public static MechSys readICfile(string fileName)
        {
            addStText("------------ Parsing the " + fileName + " ----------------");
            MechSys mSys = new MechSys();
            try
            {
                using (StreamReader sr = new StreamReader(fileName))
                {
                    string line;
                    string theWord;
                    string val;
                    int Natoms = 0;
                    while ((line = sr.ReadLine()) != null)
                    {
                        if ((line = line.Trim()) == null || line.Length < 1)
                            continue;
                        if (line[0].ToString() == commentSign)
                            continue; //ignor the line if it is a comment
                        theWord = readAWord(line);
                        line = line.Remove(0, theWord.Length).Trim(); //delete the word has been read
                        switch (theWord)
                        {
                            case IC_FIELD_BOX:
                                val = readAWord(line);
                                addStText(IC_FIELD_BOX + " = " + val );
                                mSys.boxL = dblParse(val);
                                break;
                            case IC_FIELD_NATOMS:
                                val = readAWord(line);
                                addStText(IC_FIELD_NATOMS + " = " + val);
                                Natoms = Convert.ToInt32(val);
                                break;
                            case IC_FIELD_ATOMINF:
                                int i = 0;
                                Atom[] atoms = new Atom[Natoms];
                                while (i++ < Natoms && (line = sr.ReadLine()) != null)
                                {
                                    line = line.Trim();
                                    if (line[0].ToString() == commentSign)
                                        continue; //ignor the line if it is a comment
                                    string sort;
                                    double[] pos = new double[3];
                                    double[] vel = new double[3] {0d, 0d, 0d};
                                    int j = 0;
                                    string dbgTxt = ""; 
                                    
                                    //read the atom sort
                                    val = readAWord(line);
                                    if (val == null)
                                    {
                                        addStText("Unknown IC atom info : " + line, StatusWindow.TXT_ERROR);
                                        return null;
                                    }
                                    sort = val;
                                    line = line.Remove(0, val.Length).Trim();
                                    dbgTxt += val;

                                    //read the atom's position
                                    for(j = 0; j < 3; j++)
                                    {
                                        dbgTxt += "    ";
                                        val = readAWord(line);
                                        if (val == null)
                                            continue;
                                        dbgTxt += val;
                                        pos[j] = dblParse(val);
                                        line = line.Remove(0, val.Length).Trim();
                                    }
                                    //read the atom's velocieties
                                    for (j = 0; j < 3; j++)
                                    {
                                        dbgTxt += "    ";
                                        val = readAWord(line);
                                        if (val == null)
                                            continue;
                                        dbgTxt += val;
                                        vel[j] = dblParse(val);
                                        line = line.Remove(0, val.Length).Trim();
                                    }
                                    addStText(dbgTxt);
                                    atoms[i - 1] = new Atom(pos, vel, Atom.ATOM_SORT_NA);
                                }
                                mSys.addAtoms(atoms);
                                addStText("   mech system size = " + mSys.Count.ToString());
                                break;
                            //ToDo: parse velocities and atoms types
                            default:
                                addStText("Unknown IC entrence : " + theWord, StatusWindow.TXT_WARNING);
                                break;
                        }
                    } 
                }
            }
            catch (Exception e)
            {
                addStText(e.Message + "\n" + "  Stack : " + e.StackTrace, StatusWindow.TXT_ERROR);                               
            }
            addStText("\\-------------- Parsing DONE ------------------------/");
            return mSys;
        }

        private static string readAWord(string str)
        {
            if (str == null || str.Length == 0)
                return null;
            char[] chWord;
            str = str.Trim();
            int l = str.IndexOf(" ");
            chWord = new char[l < 1 ? str.Length : l];
            for (int i = 0; i < str.Length; i++)
            {
                if (Char.IsWhiteSpace(str[i]))
                    break;
                chWord[i] = str[i];
            }
            return new String(chWord);
        }

        private static double dblParse(string val)
        {
            val = val.Replace('.',',');
            return Convert.ToDouble(val);
        }

        private static void addStText(string txt, byte type)
        {
            _stWindow().addText(txt, type);
        }

        private static void addStText(string txt)
        {
            _stWindow().addText(txt, StatusWindow.TXT_ORDINARY);
        }
    }
}
